{-----------------------------------------------------------------
 
  this module tests the DEPEND parsing facility

  (c) 2008 Markus Dittrich 
 
  This program is free software; you can redistribute it 
  and/or modify it under the terms of the GNU General Public 
  License Version 3 as published by the Free Software Foundation. 
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License Version 3 for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 59 Temple Place - Suite 330, 
  Boston, MA 02111-1307, USA.

--------------------------------------------------------------------}

module VersionParserTest ( version_parse_tester
                         , version_compare_tester
                         ) where

-- basic imports
import qualified Data.ByteString as B(ByteString)
import qualified Data.ByteString.Char8 as BC
import Control.Monad
import Prelude
import System.IO


-- local imports
import Helpers.PrettyPrint
import Helpers.ByteString
import TestHelpers
import Parsers.Version
import Drivers.Version


--
-- main driver to test parsing of dependencies
--
version_parse_tester :: IO Bool
version_parse_tester = do

        parseRes <- foldM check_version_parser True testParseVersions
        return parseRes


--
-- check if a particular version string parser properly
-- into tokens
--
check_version_parser :: Bool -> VersionTestItem -> IO Bool
check_version_parser state item = do

  -- short message
  putColorStr Cyan   $ "Testing version parser -- "
  putColorBStr White $ (versionString item) 
  putColorStr Cyan   $ " ... "

  -- parse and compare
  let parseResult = split_version $ versionString item
  if parseResult == parsedVersion item 
    then do
      print_success
      return (state && True)
    else do
      print_failure
      return (state && False)


--
-- main driver for checking if comparing versions works
--
version_compare_tester :: IO Bool
version_compare_tester = do

        compRes <- foldM check_version_comparator True testCompVersions
        return compRes



--
-- check if comparing two particular versions leads to the
-- expected results
--
check_version_comparator :: Bool -> VersionCompareItem -> IO Bool
check_version_comparator state item = do

  -- short message 
  putColorStr Cyan    $ "Testing version comparator -- "
  putColorBStr White  $ (firstV item)
  putColorStr Magenta $ " <> "
  putColorBStr White  $ (secondV item)
  putColorStr Cyan    $ " ... "

  -- compare
  let compResult = (comparator item) (firstV item) (secondV item)
  if compResult == (result item) 
    then do
      print_success
      return (state && True)
    else do
      print_failure
      return (state && False)


------------------------------------------------------------------
-- beginning of section describing test and expected results
--
-- NOTE: To add a new test simply define a ref_<name> 
-- ReferenceData structure with the expected values and add
-- the new test to dependTests with the search string supplied
-- as a String
------------------------------------------------------------------

-- 
-- define small helper data type that holds a versions
-- item as ByteString as well as a parsed list of VersionTok
--
data VersionTestItem = VersionTestItem 
  {   
    versionString :: B.ByteString
  , parsedVersion :: [VersionTok]
  }


--
-- a few small helpers to simplify live
--
emptyTok :: VersionTok
emptyTok = NumTok $ BC.pack ""

zeroTok :: VersionTok
zeroTok = NumTok $ BC.pack "0"

oneTok :: VersionTok
oneTok = NumTok $ BC.pack "1"

twoTok :: VersionTok
twoTok = NumTok $ BC.pack "2"

fourTok :: VersionTok
fourTok = NumTok $ BC.pack "4"

aTok :: VersionTok
aTok   = NumTok $ BC.pack "a"

bTok :: VersionTok
bTok   = NumTok $ BC.pack "b"

globTok :: VersionTok
globTok = NumTok glob


--
-- test data sets to check correct parsing of version
-- strings
-- 

-- test parser data 1
version1 :: VersionTestItem
version1 = VersionTestItem
  {
    versionString = BC.pack "1.1.2"
  , parsedVersion = [oneTok, oneTok, twoTok]
  }


-- test parser data 2
version2 :: VersionTestItem
version2 = VersionTestItem
  {
    versionString = BC.pack "1.1.2.1"
  , parsedVersion = [oneTok, oneTok, twoTok, oneTok]
  }


-- test parser data 3
version3 :: VersionTestItem
version3 = VersionTestItem
  {
    versionString = BC.pack "1.1.2.1a"
  , parsedVersion = [oneTok, oneTok, twoTok, oneTok, aTok]
  }


-- test parser data 4
version4 :: VersionTestItem
version4 = VersionTestItem
  {
    versionString = BC.pack "1.1.2.1b"
  , parsedVersion = [oneTok, oneTok, twoTok, oneTok, bTok]
  }


-- test parser data 5
version5 :: VersionTestItem
version5 = VersionTestItem
  {
    versionString = BC.pack "1.1.2.1b-alpha"
  , parsedVersion = [oneTok, oneTok, twoTok, oneTok, bTok, 
      Suffix Alpha, emptyTok]
  }


-- test parser data 6
version6 :: VersionTestItem
version6 = VersionTestItem
  {
    versionString = BC.pack "1.1.2.1b-beta"
  , parsedVersion = [oneTok, oneTok, twoTok, oneTok, bTok, 
      Suffix Beta, emptyTok]
  }



-- test parser data 7
version7 :: VersionTestItem
version7 = VersionTestItem
  {
    versionString = BC.pack "1.1.2.1b-beta2"
  , parsedVersion = [oneTok, oneTok, twoTok, oneTok, bTok, 
      Suffix Beta, twoTok]
  }


-- test parser data 8
version8 :: VersionTestItem
version8 = VersionTestItem
  {
    versionString = BC.pack "1.1.2.1b-beta2-pre"
  , parsedVersion = [oneTok, oneTok, twoTok, oneTok, bTok, 
      Suffix Beta, twoTok, Suffix Pre, emptyTok]
  }


-- test parser data 9
version9 :: VersionTestItem
version9 = VersionTestItem
  {
    versionString = BC.pack "1.1.2.1b-beta2-p"
  , parsedVersion = [oneTok, oneTok, twoTok, oneTok, bTok, 
      Suffix Beta, twoTok, Suffix P, emptyTok]
  }


-- test parser data 10
version10 :: VersionTestItem
version10 = VersionTestItem
  {
    versionString = BC.pack "1.1.2.1b-beta2-p-r1"
  , parsedVersion = [oneTok, oneTok, twoTok, oneTok, bTok, 
      Suffix Beta, twoTok, Suffix P, emptyTok, Revision, oneTok]
  }


-- test parser data 11
version11 :: VersionTestItem
version11 = VersionTestItem
  {
    versionString = BC.pack "2.20081023a-r1"
  , parsedVersion = [twoTok, NumTok $ BC.pack "20081023", aTok, 
      Revision, oneTok]
  }


-- test parser data 12
version12 :: VersionTestItem
version12 = VersionTestItem
  {
    versionString = BC.pack "2.20081123b"
  , parsedVersion = [twoTok, NumTok $ BC.pack "20081123", bTok] 
  }


-- test parser data 13
version13 :: VersionTestItem
version13 = VersionTestItem
  {
    versionString = BC.pack "1.22.2"
  , parsedVersion = [oneTok, NumTok $ BC.pack "22", twoTok]
  }


-- test parser data 14
version14 :: VersionTestItem
version14 = VersionTestItem
  {
    versionString = BC.pack "1.4.2"
  , parsedVersion = [oneTok, NumTok $ BC.pack "4", twoTok]
  }


-- test parser data 15
version15 :: VersionTestItem
version15 = VersionTestItem
  {
    versionString = BC.pack "1.1.2.0"
  , parsedVersion = [oneTok, oneTok, twoTok, zeroTok]
  }


-- test parser data 16
version16 :: VersionTestItem
version16 = VersionTestItem
  {
    versionString = BC.pack "1.1.2.0.0.0"
  , parsedVersion = [oneTok, oneTok, twoTok, zeroTok, zeroTok, zeroTok]
  }


-- test parser data 17
version17 :: VersionTestItem
version17 = VersionTestItem
  {
    versionString = BC.pack "1.2*"
  , parsedVersion = [oneTok, twoTok, globTok]
  }


-- test parser data 18
version18 :: VersionTestItem
version18 = VersionTestItem
  {
    versionString = BC.pack "1.1*"
  , parsedVersion = [oneTok, oneTok, globTok]
  }


-- test parser data 19
version19 :: VersionTestItem
version19 = VersionTestItem
  {
    versionString = BC.pack "2*"
  , parsedVersion = [twoTok, globTok]
  }


-- test parser data 20
version20 :: VersionTestItem
version20 = VersionTestItem
  {
    versionString = BC.pack "1.1.2-r5"
  , parsedVersion = [oneTok, oneTok, twoTok, Revision, 
                     NumTok $ BC.pack "5"]
  }


-- test parser data 21
version21 :: VersionTestItem
version21 = VersionTestItem
  {
    versionString = BC.pack "2.20081023a-r4"
  , parsedVersion = [twoTok, NumTok $ BC.pack "20081023", aTok, 
      Revision, fourTok]
  }



-- list all version string to be tested
testParseVersions :: [VersionTestItem]
testParseVersions = [version1, version2, version3, version4, version5,
                     version6, version7, version8, version9, version10,
                     version11, version12, version13, version14,
                     version15, version16, version17, version18,
                     version19, version20, version21]



-- 
-- test data sets for checking correct comparison of version
-- string
--

--
-- helper data structure
--
data VersionCompareItem = VersionCompareItem 
  {
      firstV     :: B.ByteString
    , secondV    :: B.ByteString
    , comparator :: B.ByteString -> B.ByteString -> Bool
    , result     :: Bool
  }


-- test compare data 1
versionComp1 :: VersionCompareItem
versionComp1 = VersionCompareItem
  {
    firstV     = versionString version1
  , secondV    = versionString version2
  , comparator = is_larger
  , result     = False
  }


-- test compare data 2
versionComp2 :: VersionCompareItem
versionComp2 = VersionCompareItem
  {
    firstV     = versionString version1
  , secondV    = versionString version2
  , comparator = is_smaller
  , result     = True
  }


-- test compare data 3
versionComp3 :: VersionCompareItem
versionComp3 = VersionCompareItem
  {
    firstV     = versionString version2
  , secondV    = versionString version3
  , comparator = is_smaller
  , result     = True
  }


-- test compare data 4
versionComp4 :: VersionCompareItem
versionComp4 = VersionCompareItem
  {
    firstV     = versionString version3
  , secondV    = versionString version2
  , comparator = is_larger
  , result     = True
  }


-- test compare data 5
versionComp5 :: VersionCompareItem
versionComp5 = VersionCompareItem
  {
    firstV     = versionString version3
  , secondV    = versionString version2
  , comparator = is_larger_equal
  , result     = True
  }


-- test compare data 6
versionComp6 :: VersionCompareItem
versionComp6 = VersionCompareItem
  {
    firstV     = versionString version4
  , secondV    = versionString version3
  , comparator = is_larger
  , result     = True
  }


-- test compare data 7
versionComp7 :: VersionCompareItem
versionComp7 = VersionCompareItem
  {
    firstV     = versionString version5
  , secondV    = versionString version4
  , comparator = is_larger
  , result     = True
  }


-- test compare data 8
versionComp8 :: VersionCompareItem
versionComp8 = VersionCompareItem
  {
    firstV     = versionString version6
  , secondV    = versionString version5
  , comparator = is_larger
  , result     = True
  }


-- test compare data 9
versionComp9 :: VersionCompareItem
versionComp9 = VersionCompareItem
  {
    firstV     = versionString version7
  , secondV    = versionString version6
  , comparator = is_larger
  , result     = True
  }


-- test compare data 10 
versionComp10 :: VersionCompareItem
versionComp10 = VersionCompareItem
  {
    firstV     = versionString version8
  , secondV    = versionString version7
  , comparator = is_larger
  , result     = True
  }


-- test compare data 11
versionComp11 :: VersionCompareItem
versionComp11 = VersionCompareItem
  {
    firstV     = versionString version9
  , secondV    = versionString version8
  , comparator = is_larger
  , result     = True
  }


-- test compare data 12
versionComp12 :: VersionCompareItem
versionComp12 = VersionCompareItem
  {
    firstV     = versionString version10
  , secondV    = versionString version9
  , comparator = is_larger
  , result     = True
  }


-- test compare data 13
versionComp13 :: VersionCompareItem
versionComp13 = VersionCompareItem
  {
    firstV     = versionString version7
  , secondV    = versionString version8
  , comparator = is_smaller
  , result     = True
  }


-- test compare data 14
versionComp14 :: VersionCompareItem
versionComp14 = VersionCompareItem
  {
    firstV     = versionString version3
  , secondV    = versionString version7
  , comparator = is_larger
  , result     = False
  }


-- test compare data 15
versionComp15 :: VersionCompareItem
versionComp15 = VersionCompareItem
  {
    firstV     = versionString version6
  , secondV    = versionString version9
  , comparator = is_smaller
  , result     = True
  }


-- test compare data 16
versionComp16 :: VersionCompareItem
versionComp16 = VersionCompareItem
  {
    firstV     = versionString version4
  , secondV    = versionString version10
  , comparator = is_smaller
  , result     = True
  }


-- test compare data 17
versionComp17 :: VersionCompareItem
versionComp17 = VersionCompareItem
  {
    firstV     = versionString version11
  , secondV    = versionString version12
  , comparator = is_smaller
  , result     = True
  }


-- test compare data 18
versionComp18 :: VersionCompareItem
versionComp18 = VersionCompareItem
  {
    firstV     = versionString version11
  , secondV    = versionString version1
  , comparator = is_larger
  , result     = True
  }


-- test compare data 19
versionComp19 :: VersionCompareItem
versionComp19 = VersionCompareItem
  {
    firstV     = versionString version13
  , secondV    = versionString version14
  , comparator = is_larger
  , result     = True
  }


-- test compare data 20
versionComp20 :: VersionCompareItem
versionComp20 = VersionCompareItem
  {
    firstV     = versionString version1
  , secondV    = versionString version15
  , comparator = is_larger_equal
  , result     = True
  }


-- test compare data 21
versionComp21 :: VersionCompareItem
versionComp21 = VersionCompareItem
  {
    firstV     = versionString version15
  , secondV    = versionString version16
  , comparator = is_larger_equal
  , result     = True
  }


-- test compare data 22
versionComp22 :: VersionCompareItem
versionComp22 = VersionCompareItem
  {
    firstV     = versionString version16
  , secondV    = versionString version17
  , comparator = is_smaller
  , result     = True
  }


-- test compare data 23
versionComp23 :: VersionCompareItem
versionComp23 = VersionCompareItem
  {
    firstV     = versionString version14
  , secondV    = versionString version17
  , comparator = is_larger_equal
  , result     = True
  }


-- test compare data 24
versionComp24 :: VersionCompareItem
versionComp24 = VersionCompareItem
  {
    firstV     = versionString version16
  , secondV    = versionString version18
  , comparator = is_equal
  , result     = True
  }


-- test compare data 25
versionComp25 :: VersionCompareItem
versionComp25 = VersionCompareItem
  {
    firstV     = versionString version18
  , secondV    = versionString version2
  , comparator = is_equal
  , result     = True
  }


-- test compare data 26
versionComp26 :: VersionCompareItem
versionComp26 = VersionCompareItem
  {
    firstV     = versionString version18
  , secondV    = versionString version4
  , comparator = is_equal
  , result     = True
  }


-- test compare data 27
versionComp27 :: VersionCompareItem
versionComp27 = VersionCompareItem
  {
    firstV     = versionString version18
  , secondV    = versionString version7
  , comparator = is_equal
  , result     = True
  }


-- test compare data 28
versionComp28 :: VersionCompareItem
versionComp28 = VersionCompareItem
  {
    firstV     = versionString version18
  , secondV    = versionString version8
  , comparator = is_equal
  , result     = True
  }


-- test compare data 29
versionComp29 :: VersionCompareItem
versionComp29 = VersionCompareItem
  {
    firstV     = versionString version17
  , secondV    = versionString version2
  , comparator = is_larger
  , result     = True
  }


-- test compare data 30
versionComp30 :: VersionCompareItem
versionComp30 = VersionCompareItem
  {
    firstV     = versionString version17
  , secondV    = versionString version4
  , comparator = is_larger
  , result     = True
  }


-- test compare data 31
versionComp31 :: VersionCompareItem
versionComp31 = VersionCompareItem
  {
    firstV     = versionString version17
  , secondV    = versionString version7
  , comparator = is_larger
  , result     = True
  }


-- test compare data 32
versionComp32 :: VersionCompareItem
versionComp32 = VersionCompareItem
  {
    firstV     = versionString version17
  , secondV    = versionString version8
  , comparator = is_larger
  , result     = True
  }


-- test compare data 33
versionComp33 :: VersionCompareItem
versionComp33 = VersionCompareItem
  {
    firstV     = versionString version19
  , secondV    = versionString version12
  , comparator = is_equal
  , result     = True
  }


-- test compare data 34
versionComp34 :: VersionCompareItem
versionComp34 = VersionCompareItem
  {
    firstV     = versionString version19
  , secondV    = versionString version11
  , comparator = is_equal
  , result     = True
  }


-- test compare data 35
versionComp35 :: VersionCompareItem
versionComp35 = VersionCompareItem
  {
    firstV     = versionString version2
  , secondV    = versionString version17
  , comparator = is_smaller
  , result     = True
  }


-- test compare data 36
versionComp36 :: VersionCompareItem
versionComp36 = VersionCompareItem
  {
    firstV     = versionString version4
  , secondV    = versionString version17
  , comparator = is_smaller
  , result     = True
  }


-- test compare data 37
versionComp37 :: VersionCompareItem
versionComp37 = VersionCompareItem
  {
    firstV     = versionString version5
  , secondV    = versionString version17
  , comparator = is_smaller
  , result     = True
  }


-- test compare data 38
versionComp38 :: VersionCompareItem
versionComp38 = VersionCompareItem
  {
    firstV     = versionString version9
  , secondV    = versionString version17
  , comparator = is_smaller
  , result     = True
  }


-- test compare data 39
versionComp39 :: VersionCompareItem
versionComp39 = VersionCompareItem
  {
    firstV     = versionString version20
  , secondV    = versionString version1
  , comparator = is_same_rev_class 
  , result     = True
  }


-- test compare data 40
versionComp40 :: VersionCompareItem
versionComp40 = VersionCompareItem
  {
    firstV     = versionString version20
  , secondV    = versionString version11
  , comparator = is_same_rev_class
  , result     = False
  }


-- test compare data 41
versionComp41 :: VersionCompareItem
versionComp41 = VersionCompareItem
  {
    firstV     = versionString version21
  , secondV    = versionString version11
  , comparator = is_same_rev_class
  , result     = True
  }


-- list all version comparison tests to be run
testCompVersions :: [VersionCompareItem]
testCompVersions = [versionComp1, versionComp2, versionComp3,
  versionComp4, versionComp5, versionComp6, versionComp7,
  versionComp8, versionComp9, versionComp10, versionComp11,
  versionComp12, versionComp13, versionComp14, versionComp15,
  versionComp16, versionComp17, versionComp18, versionComp19,
  versionComp20, versionComp21, versionComp22, versionComp23,
  versionComp24, versionComp25, versionComp26, versionComp27,
  versionComp28, versionComp29, versionComp30, versionComp31,
  versionComp32, versionComp33, versionComp34, versionComp35,
  versionComp36, versionComp37, versionComp38, versionComp39,
  versionComp40, versionComp41]



------------------------------------------------------------------
-- end of section describing test and expected results
------------------------------------------------------------------


